package com.example.hackotontest.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.hackotontest.R;
import com.example.hackotontest.dto.UserStoryDto;

public class ClientActivity extends Activity {

	private static final String GET_FREE_PORT_COMMAND = "getFreePort";

	private final int PICKER = 1;
	private String messageForScrumMaster = GET_FREE_PORT_COMMAND;
	private Gallery picGallery;
	private ImageView picView;
	private String username;

	private CardAdapter cardAdapter;

	// client for scrum master related fields
	private String scrumMasterIpAddress = "10.0.2.2";
	private boolean connected = false;
	Socket socket = null;
	private boolean firstConnect = true;

	// server to listen for messages from scrum master related fields
	private Handler handler = new Handler();
	private static final String SALAHOR_SERVER_IP = "10.0.2.15";
	private ServerSocket serverSocket;
	private TextView userStory;
	private int listeningPort = 0;

	private static Map<Integer, String> indexValueMap = new HashMap<Integer, String>();

	static {
		indexValueMap.put(0, "?");
		indexValueMap.put(1, "1/2");
		indexValueMap.put(2, "1");
		indexValueMap.put(3, "2");
		indexValueMap.put(4, "3");
		indexValueMap.put(5, "5");
		indexValueMap.put(6, "8");
		indexValueMap.put(7, "13");
		indexValueMap.put(8, "20");
		indexValueMap.put(9, "40");
		indexValueMap.put(10, "100");
		indexValueMap.put(11, "Coffe Break");
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.clientview);

		// picView = (ImageView) findViewById(R.id.picture);
		userStory = (TextView) findViewById(R.id.userStory);
		picGallery = (Gallery) findViewById(R.id.gallery);

		cardAdapter = new CardAdapter(this);
		picGallery.setAdapter(cardAdapter);

		// get the username
		Intent intent = getIntent();
		username = intent.getStringExtra("username");

		sendMessageToScrumMaster();

		registerCardListener();

	}

	private void startTCPServer() {
		Thread fst = new Thread(new ServerThread());
		fst.start();
	}

	private void registerCardListener() {
		picGallery.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
				System.out.println("-----------------------Picture Clicked");
				messageForScrumMaster = indexValueMap.get(position);
				sendMessageToScrumMaster();
				return true;
			}
		});
	}

	private void sendMessageToScrumMaster() {
		Thread cThread = new Thread(new ClientThread());
		cThread.start();
	}

	public class ClientThread implements Runnable {

		public void run() {
			try {

				if (!connected) {
					InetAddress serverAddr = InetAddress.getByName(scrumMasterIpAddress);
					Log.d("ClientActivity", "P: Connecting...");
					socket = new Socket(serverAddr, 8081);
					connected = true;
				}
				// while (connected) {
				try {
					Log.d("ClientActivity", "P: Sending command.");
					PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
					BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

					if (listeningPort == 0) {
						String line = in.readLine();
						listeningPort = Integer.valueOf(line);
						startTCPServer();
					} else {
						out.println(username + " : " + messageForScrumMaster);
					}
					Log.d("ClientActivity", "P: Sent.");
				} catch (Exception e) {
					Log.e("ClientActivity", "P: Error", e);
				}
				// }
				// socket.close();
				// Log.d("ClientActivity", "C: Closed.");
			} catch (Exception e) {
				Log.e("ClientActivity", "C: Error", e);
				connected = false;
			}
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			System.out.println("-----------------------------Activity Result OK");
			if (requestCode == PICKER) {
				System.out.println("-----------------------------Activity Result OK");
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	// server side
	public class ServerThread implements Runnable {

		public void run() {
			try {
				if (SALAHOR_SERVER_IP != null) {
					handler.post(new Runnable() {
						@Override
						public void run() {
							userStory.setText("Listening on IP: " + SALAHOR_SERVER_IP);
						}
					});
					serverSocket = new ServerSocket(listeningPort);
					// while (true) {
					// listen for incoming clients
					Socket client = serverSocket.accept();
					handler.post(new Runnable() {
						@Override
						public void run() {
							userStory.setText("Connected.");
						}
					});
					while (true) {
						try {
							// BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
							ObjectInputStream objectInputStream = new ObjectInputStream(client.getInputStream());

							UserStoryDto socketDTO = (UserStoryDto) objectInputStream.readObject();
							// (UserStoryDto) objectInputStream.readObject();
							// while ((socketDTO = (UserStoryDto) objectInputStream.readObject()) != null) {
							final UserStoryDto reportSocketDTO = socketDTO;
							Log.d("ServerActivity", socketDTO.toString());
							handler.post(new Runnable() {
								@Override
								public void run() {
									userStory.setText(reportSocketDTO.getUserStoryText());
								}
							});
							// }
						} catch (Exception e) {
							handler.post(new Runnable() {
								@Override
								public void run() {
									userStory.setText("Oops. Connection interrupted. Please reconnect your phones.");
								}
							});
							e.printStackTrace();
						}
						// }
					}
				} else {
					handler.post(new Runnable() {
						@Override
						public void run() {
							userStory.setText("Couldn't detect internet connection.");
						}
					});
				}
			} catch (Exception e) {
				handler.post(new Runnable() {
					@Override
					public void run() {
						userStory.setText("Error");
					}
				});
				e.printStackTrace();
			}
		}
	}
}
